package simulaco.business;

import gminet.infra.business.BusinessException;
import gminet.infra.business.BusinessObject;
import gminet.infra.db.Transaction;
import gminet.infra.db.TransactionException;
import gminet.infra.toolkit.DateToolkit;
import gminet.infra.toolkit.NumberToolkit;
import gminet.infra.toolkit.StringToolkit;

import java.sql.Connection;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import simulaco.dao.ConcursoDAO;
import simulaco.dao.ConcursoFilter;
import simulaco.dao.OrgaoDAO;
import simulaco.dao.OrgaoFilter;
import simulaco.dto.Orgao;
import simulaco.dto.Situacao;

public class OrgaoBusiness extends BusinessObject {

    private static List<Orgao> CACHE_LIST_ORGAOS = null;
    private static List<Orgao> CACHE_LIST_ORGAOS_ACTIVES = null;

    public static Orgao findByPK(int orgaoId) throws TransactionException {

        Orgao orgao = null;
        Transaction transaction = createTransaction();
        try {
            Connection conn = transaction.getConnection();
            orgao = OrgaoDAO.findByPK(orgaoId, conn);
        } finally {
            transaction.release();
        }
        return orgao;
    }

    public static List<Orgao> findAll() throws TransactionException {

        if (CACHE_LIST_ORGAOS == null || CACHE_LIST_ORGAOS.size() == 0) {
            List<Orgao> orgaos = null;
            Transaction transaction = createTransaction();
            try {
                Connection conn = transaction.getConnection();
                orgaos = OrgaoDAO.findAll(conn);
            } catch (TransactionException te) {
                transaction.rollback();
                throw te;
            } finally {
                transaction.release();
            }
            // CACHE
            if (CACHE_LIST_ORGAOS == null) {
                CACHE_LIST_ORGAOS = new ArrayList<Orgao>();
            }
            CACHE_LIST_ORGAOS.addAll(orgaos);
        }
        return CACHE_LIST_ORGAOS;
    }

    public static List<Orgao> findActives() throws TransactionException {

        if (CACHE_LIST_ORGAOS_ACTIVES == null || CACHE_LIST_ORGAOS_ACTIVES.size() == 0) {
            List<Orgao> orgaos = null;
            Transaction transaction = createTransaction();
            try {
                Connection conn = transaction.getConnection();
                OrgaoFilter filter = new OrgaoFilter();
                filter.setCodigoSituacao(Situacao.HABILITADO.getCodigo());
                orgaos = OrgaoDAO.findByFilter(filter, conn);
            } catch (TransactionException te) {
                transaction.rollback();
                throw te;
            } finally {
                transaction.release();
            }
            // CACHE
            if (CACHE_LIST_ORGAOS_ACTIVES == null) {
                CACHE_LIST_ORGAOS_ACTIVES = new ArrayList<Orgao>();
            }
            CACHE_LIST_ORGAOS_ACTIVES.addAll(orgaos);
        }
        return CACHE_LIST_ORGAOS_ACTIVES;
    }

    public static Orgao insert(Orgao orgao) throws BusinessException, TransactionException {

        Orgao newOrgao = null;
        Transaction transaction = createTransaction();
        try {
            Connection conn = transaction.getConnection();
            // CONCURSO
            Date dataAtual = DateToolkit.getDate();
            int rangeId = createRangeId(orgao.getNome());
            orgao.setCodigo(OrgaoDAO.getNextCodigo(conn, rangeId, rangeId + 1000));
            if (orgao.getSituacao().getCodigo() == 0) {
                orgao.setSituacao(Situacao.DESABILITADO);
            }
            orgao.setDataCadastro(dataAtual);
            OrgaoDAO.insert(orgao, conn);
            // COMMIT
            transaction.commit();
            // RELEASE CACHE
            releaseCache();
            //
            newOrgao = orgao;
        } catch (TransactionException te) {
            transaction.rollback();
            throw te;
        } finally {
            transaction.release();
        }
        return newOrgao;
    }

    private static int createRangeId(String orgaoName) {

        String strCodigo = "1";
        String caracter1 = orgaoName.substring(0, 1).toUpperCase();
        String caracter2 = orgaoName.length() > 1 ? orgaoName.substring(1, 2).toUpperCase() : "A";
        int valor1 = Math.abs(caracter1.compareTo("A") + 1);
        if (StringToolkit.isDigit(caracter1)) {
            valor1 = 0;
        }
        int valor2 = Math.abs(caracter2.compareTo("A") / 3);
        if (StringToolkit.isDigit(caracter2)) {
            valor2 = 0;
        }
        strCodigo += NumberToolkit.getStringFromInt(Math.min(valor1, 99), 2);
        strCodigo += NumberToolkit.getStringFromInt(Math.min(valor2, 9), 1);
        strCodigo += "000";
        return Integer.parseInt(strCodigo);
    }

    public static void update(Orgao orgao) throws BusinessException, TransactionException {

        Transaction transaction = createTransaction();
        try {
            Connection conn = transaction.getConnection();
            OrgaoDAO.update(orgao, conn);
            // COMMIT
            transaction.commit();
            // RELEASE CACHE
            releaseCache();
        } catch (TransactionException te) {
            transaction.rollback();
            throw te;
        } finally {
            transaction.release();
        }
    }

    public static void updateStatus(Orgao orgao) throws BusinessException, TransactionException {

        Transaction transaction = createTransaction();
        try {
            Connection conn = transaction.getConnection();
            Orgao auxOrgao = OrgaoDAO.findByPK(orgao.getCodigo(), conn);
            auxOrgao.setSituacao(orgao.getSituacao());
            OrgaoDAO.update(auxOrgao, conn);
            // COMMIT
            transaction.commit();
            // RELEASE CACHE
            releaseCache();
        } catch (TransactionException te) {
            transaction.rollback();
            throw te;
        } finally {
            transaction.release();
        }
    }

    public static void delete(Orgao orgao) throws BusinessException, TransactionException {

        Transaction transaction = createTransaction();
        try {
            Connection conn = transaction.getConnection();
            // VERIFICA SE TEM CONCURSO VINCULADOS
            ConcursoFilter filter = new ConcursoFilter();
            filter.setCodigoOrgao(orgao.getCodigo());
            if (ConcursoDAO.findByFilter(filter, conn).size() > 0) {
                throw new BusinessException("Não é possivel excluir este orgão. Existem concursos vinculados.");
            } else {
                // EXCLUI O ORGAO
                OrgaoDAO.delete(orgao, conn);
                transaction.commit();
                // RELEASE CACHE
                releaseCache();
            }
        } catch (TransactionException te) {
            transaction.rollback();
            throw te;
        } finally {
            transaction.release();
        }
    }

    private static void releaseCache() {

        // CACHE_LIST_ORGAOS
        if (CACHE_LIST_ORGAOS != null) {
            CACHE_LIST_ORGAOS.clear();
        }
        CACHE_LIST_ORGAOS = null;
        // CACHE_LIST_ORGAOS_ACTIVES
        if (CACHE_LIST_ORGAOS_ACTIVES != null) {
            CACHE_LIST_ORGAOS_ACTIVES.clear();
        }
        CACHE_LIST_ORGAOS_ACTIVES = null;
    }

}
